package com.donleo.elastic.service.impl;

import com.donleo.elastic.common.CommonResult;
import com.donleo.elastic.mapper.RoleMapper;
import com.donleo.elastic.model.Role;
import com.donleo.elastic.repository.EsRoleRepository;
import com.donleo.elastic.service.EsRoleService;
import com.donleo.elastic.vo.EsRole;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.matchQuery;

/**
 * @author liangd
 * date 2020-12-18 09:53
 * code 数据与es交互
 */
@Service
public class EsRoleServiceImpl implements EsRoleService {

    @Autowired
    private EsRoleRepository esRoleRepository;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private ElasticsearchRestTemplate restTemplate;


    @Override
    public int importAll() {

        List<Role> roleList = roleMapper.selectList(null);
        //将roleList里面的数据浅拷贝到es中
        List<EsRole> collect = roleList.stream().map(role -> {
            EsRole esRole = new EsRole();
            BeanUtils.copyProperties(role, esRole);
            return esRole;
        }).collect(Collectors.toList());
        //方式一
//        collect.forEach(esRoleRepository::save);
        //方式二
        esRoleRepository.saveAll(collect);
        return roleList.size();
    }

    @Override
    public void delete(Integer id) {
        EsRole esRole = new EsRole();
        esRole.setId(id);
        esRoleRepository.delete(esRole);
    }

    @Override
    public Page<EsRole> search(String keyword, Integer pageNum, Integer pageSize) {
        NativeSearchQuery roleName = new NativeSearchQueryBuilder()
                .withQuery(matchQuery("roleName", keyword)).build();
        return esRoleRepository.search(roleName);
    }

    @Override
    public SearchHits searchHit(String keyword) {
        Query query = new NativeSearchQueryBuilder()
                .withQuery(matchQuery("roleName", keyword))
                .withHighlightFields(
                        new HighlightBuilder.Field("roleName")
                                .preTags("<font style='color:red'>").postTags("</font>")
                ).build();
        return restTemplate.search(query, EsRole.class);
    }

    /**
     *
     * @param roleName  高亮显示的字段
     * @return
     */
    @Override
    public CommonResult transferSearchHit(String roleName) {
        Query query = new NativeSearchQueryBuilder()
                .withQuery(matchQuery("roleName", roleName))
                .withHighlightFields(
                        new HighlightBuilder.Field("roleName")
                                .preTags("<font style='color:red'>").postTags("</font>")
                ).build();
        SearchHits<EsRole> search = restTemplate.search(query, EsRole.class);
        List<EsRole> collect = tansferSearchHitToEsRole(search);

        return CommonResult.success(collect);
    }

    /**
     * 1、获取searchHits
     * 2、获取content
     * 3、获取highlightFields
     * 4、利用反射将highlightFields的字段值赋值给context的字段值
     * 5、用collect将map对象收集起来转换为集合
     * @param search
     * @return
     */
    private List<EsRole> tansferSearchHitToEsRole(SearchHits<EsRole> search){
        List<SearchHit<EsRole>> searchHits = search.getSearchHits();
        List<EsRole> collect = searchHits.stream().map(searchHit -> {
            EsRole content = searchHit.getContent();
            Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
            highlightFields.forEach((k, v) -> {
                StringBuilder temp = new StringBuilder();
                for (String value : v) {
                    temp.append(value);
                }
                String s = temp.toString();
                try {
                    Field keyField = EsRole.class.getDeclaredField(k);
                    keyField.setAccessible(true);
                    keyField.set(content, s);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            return content;
        }).collect(Collectors.toList());
        return collect;
    }
}
